added samples
[windows-sources.git] / sdk / samples / all in on code / Visual Studio 2010 / VBFTPDownload / FTPDownloadClient.vb
blob0c9b8a7694753880bf005d0badc5021331aaf176
1 '*************************** Module Header ******************************'
2 ' Module Name: FTPDownloadClient.vb
3 ' Project: VBFTPDownload
4 ' Copyright (c) Microsoft Corporation.
5 '
6 ' This class is used to download files from a FTP server. When the download
7 ' starts, it will download the file in a background thread. The downloaded
8 ' data is stored in a MemoryStream first, and then written to local file.
9 '
11 ' This source is subject to the Microsoft Public License.
12 ' See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
13 ' All other rights reserved.
15 ' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
16 ' EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
17 ' WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
18 '*************************************************************************'
20 Imports System.IO
21 Imports System.Net
22 Imports System.Threading
24 Partial Public Class FTPClientManager
26 Public Class FTPDownloadClient
27 ' 2M bytes.
28 Public Const MaxCacheSize As Integer = 2097152
30 ' 2K bytes.
31 Public Const BufferSize As Integer = 2048
33 Private _manager As FTPClientManager
35 Public Event FileDownloadCompleted As EventHandler(Of FileDownloadCompletedEventArgs)
37 Public Event AllFilesDownloadCompleted As EventHandler
39 Public Sub New(ByVal manager As FTPClientManager)
40 If manager Is Nothing Then
41 Throw New ArgumentNullException("FTPClientManager cannot be null.")
42 End If
44 Me._manager = manager
45 End Sub
47 ''' <summary>
48 ''' Download files, directories and their subdirectories.
49 ''' </summary>
50 Public Sub DownloadDirectoriesAndFiles(ByVal files As IEnumerable(Of FTPFileSystem),
51 ByVal localPath As String)
52 If files Is Nothing Then
53 Throw New ArgumentNullException("The files to download cannot be null.")
54 End If
56 ' Create a thread to download data.
57 Dim threadStart As New ParameterizedThreadStart(
58 AddressOf StartDownloadDirectoriesAndFiles)
59 Dim downloadThread As New Thread(threadStart)
60 downloadThread.IsBackground = True
61 downloadThread.Start(New Object() {files, localPath})
62 End Sub
64 ''' <summary>
65 ''' Download files, directories and their subdirectories.
66 ''' </summary>
67 Private Sub StartDownloadDirectoriesAndFiles(ByVal state As Object)
68 Dim paras = TryCast(state, Object())
70 Dim files As IEnumerable(Of FTPFileSystem) = TryCast(paras(0),
71 IEnumerable(Of FTPFileSystem))
72 Dim localPath As String = TryCast(paras(1), String)
74 For Each file In files
75 DownloadDirectoryOrFile(file, localPath)
76 Next file
78 Me.OnAllFilesDownloadCompleted(EventArgs.Empty)
79 End Sub
81 ''' <summary>
82 ''' Download a single file or directory.
83 ''' </summary>
84 Private Sub DownloadDirectoryOrFile(ByVal fileSystem As FTPFileSystem,
85 ByVal localPath As String)
87 ' Download the file directly.
88 If Not fileSystem.IsDirectory Then
89 DownloadFile(fileSystem, localPath)
91 ' Download a directory.
92 Else
94 ' Construct the directory Path.
95 Dim directoryPath As String = localPath & "\" & fileSystem.Name
97 If Not Directory.Exists(directoryPath) Then
98 Directory.CreateDirectory(directoryPath)
99 End If
101 ' Get the sub directories and files.
102 Dim subDirectoriesAndFiles =
103 Me._manager.GetSubDirectoriesAndFiles(fileSystem.Url)
105 ' Download the files in the folder and sub directories.
106 For Each subFile In subDirectoriesAndFiles
107 DownloadDirectoryOrFile(subFile, directoryPath)
108 Next subFile
109 End If
110 End Sub
112 ''' <summary>
113 ''' Download a single file directly.
114 ''' </summary>
115 Private Sub DownloadFile(ByVal file As FTPFileSystem, ByVal localPath As String)
116 If file.IsDirectory Then
117 Throw New ArgumentException(
118 "The FTPFileSystem to download is a directory in fact")
119 End If
121 Dim destPath As String = localPath & "\" & file.Name
123 ' Create a request to the file to be downloaded.
124 Dim request As FtpWebRequest =
125 TryCast(WebRequest.Create(file.Url), FtpWebRequest)
127 request.Credentials = Me._manager.Credentials
129 ' Download file.
130 request.Method = WebRequestMethods.Ftp.DownloadFile
132 Dim response As FtpWebResponse = Nothing
133 Dim responseStream As Stream = Nothing
134 Dim downloadCache As MemoryStream = Nothing
139 ' Retrieve the response from the server and get the response stream.
140 response = TryCast(request.GetResponse(), FtpWebResponse)
142 Me._manager.OnNewMessageArrived(New NewMessageEventArg _
143 With {.NewMessage = response.StatusDescription})
145 responseStream = response.GetResponseStream()
147 ' Cache data in memory.
148 downloadCache = New MemoryStream(FTPDownloadClient.MaxCacheSize)
149 Dim downloadBuffer(FTPDownloadClient.BufferSize - 1) As Byte
151 Dim bytesSize As Integer = 0
152 Dim cachedSize As Integer = 0
154 ' Download the file until the download is completed.
157 ' Read a buffer of data from the stream.
158 bytesSize =
159 responseStream.Read(downloadBuffer, 0, downloadBuffer.Length)
161 ' If the cache is full, or the download is completed, write
162 ' the data in cache to local file.
163 If bytesSize = 0 OrElse MaxCacheSize < cachedSize + bytesSize Then
165 ' Write the data in cache to local file.
166 WriteCacheToFile(downloadCache, destPath, cachedSize)
168 ' Stop downloading the file if the download is paused,
169 ' canceled or completed.
170 If bytesSize = 0 Then
171 Exit Do
172 End If
174 ' Reset cache.
175 downloadCache.Seek(0, SeekOrigin.Begin)
176 cachedSize = 0
177 Catch ex As Exception
178 Dim msg As String =
179 String.Format("There is an error while downloading {0}. " _
180 & " See InnerException for detailed error. ",
181 file.Url)
182 Dim errorException As New ApplicationException(msg, ex)
184 ' Fire the DownloadCompleted event with the error.
185 Dim e As ErrorEventArgs = New ErrorEventArgs _
186 With {.ErrorException = errorException}
188 Me._manager.OnErrorOccurred(e)
190 Return
191 End Try
193 End If
195 ' Write the data from the buffer to the cache in memory.
196 downloadCache.Write(downloadBuffer, 0, bytesSize)
197 cachedSize += bytesSize
198 Loop
200 Dim fileDownloadCompletedEventArgs_Renamed =
201 New FileDownloadCompletedEventArgs _
202 With {.LocalFile = New FileInfo(destPath), .ServerPath = file.Url}
204 Me.OnFileDownloadCompleted(fileDownloadCompletedEventArgs_Renamed)
205 Finally
206 If response IsNot Nothing Then
207 response.Close()
208 End If
210 If responseStream IsNot Nothing Then
211 responseStream.Close()
212 End If
214 If downloadCache IsNot Nothing Then
215 downloadCache.Close()
216 End If
217 End Try
218 End Sub
220 ''' <summary>
221 ''' Write the data in cache to local file.
222 ''' </summary>
223 Private Sub WriteCacheToFile(ByVal downloadCache As MemoryStream,
224 ByVal downloadPath As String,
225 ByVal cachedSize As Integer)
226 Using fileStream_Renamed As New FileStream(downloadPath, FileMode.Append)
227 Dim cacheContent(cachedSize - 1) As Byte
228 downloadCache.Seek(0, SeekOrigin.Begin)
229 downloadCache.Read(cacheContent, 0, cachedSize)
230 fileStream_Renamed.Write(cacheContent, 0, cachedSize)
231 End Using
232 End Sub
234 Protected Overridable Sub OnFileDownloadCompleted(ByVal e As FileDownloadCompletedEventArgs)
236 RaiseEvent FileDownloadCompleted(Me, e)
237 End Sub
239 Protected Overridable Sub OnAllFilesDownloadCompleted(ByVal e As EventArgs)
240 RaiseEvent AllFilesDownloadCompleted(Me, e)
241 End Sub
242 End Class
243 End Class